package request_key

import (
	"context"
	"github.com/google/uuid"
	"google.golang.org/grpc/metadata"
	"pay/pkg/log"
	"strings"
	"time"
)

const (
	RequestIDKeyString = "X-Request-ID"
	requestIDKEYLogger = "request_id"
)

var (
	RequestIDKeyStringLower = strings.ToLower(RequestIDKeyString)
	requestContextKey       = struct{}{}
)

func GetSingleMetaData(ctx context.Context, key, defaultValue string) string {
	if md, ok := metadata.FromIncomingContext(ctx); ok {
		values := md.Get(key)
		if len(values) == 1 {
			return values[0]
		}
	}
	return defaultValue
}

// UpdateContextWithMetaRequestID
func UpdateContextWithMetaRequestID(ctx context.Context) context.Context {
	reqID := GetSingleMetaData(ctx, RequestIDKeyStringLower, "")
	if reqID == "" {
		reqID = uuid.New().String()
	}
	return FillContextWithRequestID(ctx, reqID)
}

// NewContextWithReqID
func NewContextWithReqID(ctx context.Context) context.Context {
	reqID := GetRequestID(ctx)
	if reqID == "" {
		reqID = uuid.New().String()
	}
	return FillContextWithRequestID(context.Background(), reqID)
}

// FillContextWithRequestID
func FillContextWithRequestID(ctx context.Context, reqID string) context.Context {
	logger := log.FromContext(ctx).With(requestIDKEYLogger, reqID)
	ctx = log.WithLogger(ctx, logger)
	ctx = context.WithValue(ctx, requestContextKey, reqID)
	return ctx
}

// GenerateContextWithRequestID
func GenerateContextWithRequestID(reqID string) context.Context {
	return FillContextWithRequestID(context.Background(), reqID)
}

// GenerateNSQContext
func GenerateNSQContext() context.Context {
	return GenerateContextWithRequestID(uuid.New().String())
}

func GetRequestID(ctx context.Context) string {
	reqID, _ := ctx.Value(requestContextKey).(string)
	return reqID
}

func NewOutGoingContext(ctx context.Context, timeout time.Duration) (context.Context, func()) {
	return context.WithTimeout(
		metadata.NewOutgoingContext(
			ctx, metadata.Pairs("x-request-id", GetRequestID(ctx))),
		timeout)
}
